package com.zlzlib.librefresh;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;

import androidx.core.view.ViewCompat;
import androidx.core.view.ViewPropertyAnimatorCompat;
import androidx.core.view.ViewPropertyAnimatorUpdateListener;


/**
 * 下拉刷新和上拉加载的基本类
 *
 * @DateTime: 2020/8/5 10:07
 * @Author zlz
 * @Version 1.0
 */
public abstract class BaseRefreshLayout extends FrameLayout {
    //一些初始常量值
    private final static int DEFAULT_WAVE_HEIGHT = 140;
    private final static int HIGHER_WAVE_HEIGHT = 180;
    private final static int DEFAULT_HEAD_HEIGHT = 70;
    private final static int HIGHER_HEAD_HEIGHT = 100;
    private final static int DEFAULT_FOOT_HEIGHT = 50;
    private final static int HIGHER_FOOT_HEIGHT = 70;

    //内容部分会不会跟着下拉一起向下移动
    private boolean isOverlay;
    //是否开启下拉加载
    private boolean isMoreLoad = false;
    //正在加载更多
    protected boolean isMoreLoading = false;
    //正在刷新
    protected boolean isRefreshing = false;
    //头部整体
    private FrameLayout mHeadLayout;
    //头部内容
    private BaseRefreshView headView;
    //头部高度  px   headHeight 转化
    private float mHeadHeight;
    //头部高度 dp
    protected float headHeight;
    //底部整体
    private FrameLayout mFootLayout;
    //底部内容
    private BaseRefreshView footView;
    //底部高度  px    footHeight 转化
    private float mFootHeight;
    //底部高度 dp
    protected float footHeight;
    //布局的内容
    private View mChildView;


    private boolean isShowWave;
    private int waveColor;
    //背景布局高度
    protected float mWaveHeight;
    private float waveHeight;
    //手指按下得y坐标
    private float mTouchY;
    //移动之后当前得y坐标
    private float mCurrentY;
    //拉动的一个加速器
    private DecelerateInterpolator decelerateInterpolator;
    //刷新监听器
    private RefreshListener refreshListener;

    protected abstract BaseRefreshView initHeadView(Context context, AttributeSet attrs, int defStyleAttr);

    protected abstract BaseRefreshView initFootView(Context context, AttributeSet attrs, int defStyleAttr);

    public BaseRefreshLayout(Context context) {
        this(context, null, 0);
    }

    public BaseRefreshLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BaseRefreshLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attrs, int defstyleAttr) {
        if (isInEditMode()) {
            return;
        }
        if (getChildCount() > 1) {
            throw new RuntimeException("can only have one child widget");
        }
        decelerateInterpolator = new DecelerateInterpolator(10);
        TypedArray t = context.obtainStyledAttributes(attrs, R.styleable.BaseRefreshLayout, defstyleAttr, 0);
        isOverlay = t.getBoolean(R.styleable.BaseRefreshLayout_brl_is_overlay, false);
        isMoreLoad = t.getBoolean(R.styleable.BaseRefreshLayout_brl_is_load_more, isMoreLoad);
        int type = t.getInt(R.styleable.BaseRefreshLayout_brl_wave_height_type, 0);
        if (type == 0) {
            setWaveDefault();
        } else {
            setWaveHigher();
        }
        waveColor = t.getColor(R.styleable.BaseRefreshLayout_brl_wave_color, Color.WHITE);
        isShowWave = t.getBoolean(R.styleable.BaseRefreshLayout_brl_is_show_wave, true);
        t.recycle();
        //初始化头部和底部的控件
        headView = initHeadView(context, attrs, defstyleAttr);
        footView = initFootView(context, attrs, defstyleAttr);
    }


    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        Context context = getContext();
        setWaveHeight(Utils.dip2px(context, waveHeight));
        setHeaderHeight(Utils.dip2px(context, headHeight));
        setFootHeight(Utils.dip2px(context, footHeight));
        mChildView = getChildAt(0);
        if (mChildView == null) {
            return;
        }
        //添加头部
        addHeadFrameLayout(context);
        if (headView != null) {
            headView.setWaveColor(waveColor);
            headView.setShowWave(isShowWave);
            setHeaderView(headView);
        }
        //添加底部
        addFootFrameLayout(context);
        if (footView != null) {
            footView.setWaveColor(waveColor);
            footView.setShowWave(isShowWave);
            setFooterView(footView);
        }
    }

    private void addHeadFrameLayout(Context context) {
        mHeadLayout = new FrameLayout(context);
        LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
        layoutParams.gravity = Gravity.TOP;
        mHeadLayout.setLayoutParams(layoutParams);
        this.addView(mHeadLayout);
    }

    private void addFootFrameLayout(Context context) {
        mFootLayout = new FrameLayout(context);
        LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
        layoutParams.gravity = Gravity.BOTTOM;
        mFootLayout.setLayoutParams(layoutParams);
        this.addView(mFootLayout);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (isRefreshing || isMoreLoading) return true;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mTouchY = ev.getY();
                mCurrentY = mTouchY;
                break;
            case MotionEvent.ACTION_MOVE:
                float currentY = ev.getY();
                float dy = currentY - mTouchY;
                if (dy > 0 && !canChildScrollUp()) {
                    if (headView != null) {
                        headView.onBegin(this);
                    }
                    return true;
                } else if (dy < 0 && !canChildScrollDown() && isMoreLoad) {
                    if (footView != null) {
                        footView.onBegin(this);
                    }
                    return true;
                }
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        if (isRefreshing || isMoreLoading) {
            return super.onTouchEvent(e);
        }
        switch (e.getAction()) {
            case MotionEvent.ACTION_MOVE:
                mCurrentY = e.getY();
                float dy = mCurrentY - mTouchY;
                float dyl = Math.min(mWaveHeight * 2, Math.abs(dy));
                if (mChildView != null) {
                    float move = decelerateInterpolator.getInterpolation(dyl / mWaveHeight / 2) * dyl / 2;
                    //判断是向上还是向下移动
                    if (dy >= 0) {
                        //下拉刷新
                        footViewMove(0);
                        headViewMove(move);
                    } else if (dy < 0 && isMoreLoad) {
                        //上拉加载更多
                        headViewMove(0);
                        footViewMove(move);
                    }
                }
                return true;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                if (mChildView != null) {
                    if (mHeadLayout.getLayoutParams().height > 0) {
                        headViewRefresh();
                    } else if (mFootLayout.getLayoutParams().height > 0 && isMoreLoad) {
                        footViewRefresh();
                    }
                }
                return true;
        }
        return super.onTouchEvent(e);
    }

    //头部移动
    private void headViewMove(float move) {
        float fraction = move / mHeadHeight;
        mHeadLayout.getLayoutParams().height = (int) move;
        mHeadLayout.requestLayout();
        if (headView != null) headView.onPull(this, fraction);
        if (!isOverlay) mChildView.setTranslationY(move);
    }

    //底部移动
    private void footViewMove(float move) {
        float fraction = move / mFootHeight;
        mFootLayout.getLayoutParams().height = (int) move;
        mFootLayout.requestLayout();
        if (footView != null) footView.onPull(this, fraction);
        if (!isOverlay) mChildView.setTranslationY(-move);
    }

    //下拉刷新
    private void headViewRefresh() {
        if (isOverlay) {
            if (mHeadLayout.getLayoutParams().height > mHeadHeight) {
                updateRefreshListener();
                mHeadLayout.getLayoutParams().height = (int) mHeadHeight;
                mHeadLayout.requestLayout();
            } else {
                mHeadLayout.getLayoutParams().height = 0;
                mHeadLayout.requestLayout();
            }
        } else {
            if (mChildView.getTranslationY() >= mHeadHeight) {
                createAnimatorTranslationY(mChildView, mHeadHeight, mHeadLayout);
                updateRefreshListener();
            } else {
                createAnimatorTranslationY(mChildView, 0, mHeadLayout);
            }
        }
    }

    //上拉加载
    private void footViewRefresh() {
        if (isOverlay) {
            if (mFootLayout.getLayoutParams().height > mFootHeight) {
                updateMoreLoadListener();
                mFootLayout.getLayoutParams().height = (int) mFootHeight;
            } else {
                mFootLayout.getLayoutParams().height = 0;
            }
            mFootLayout.requestLayout();
        } else {
            if (mChildView.getTranslationY() <= -mFootHeight) {
                createAnimatorTranslationY(mChildView, -mFootHeight, mFootLayout);
                updateMoreLoadListener();
            } else {
                createAnimatorTranslationY(mChildView, 0, mFootLayout);
            }
        }
    }

    /**
     * 自动刷新
     */
    public void autoRefresh() {
        updateRefreshListener();
        if (isOverlay) {
            mHeadLayout.getLayoutParams().height = (int) mHeadHeight;
            mHeadLayout.requestLayout();
        } else {
            createAnimatorTranslationY(mChildView, mHeadHeight, mHeadLayout);
        }
    }

    /**
     * 自动加载更多
     */
    public void autoRefreshMoreLoad() {
        if (isMoreLoad) {
            updateRefreshListener();
            if (isOverlay) {
                mFootLayout.getLayoutParams().height = (int) mFootHeight;
                mFootLayout.requestLayout();
            } else {
                createAnimatorTranslationY(mChildView, -mFootHeight, mFootLayout);
            }
        } else {
            throw new RuntimeException("you must setMoreLoad true");
        }
    }

    protected void updateRefreshListener() {
        isRefreshing = true;
        if (headView != null) {
            headView.onRefreshing(this);
        }
        if (refreshListener != null) {
            refreshListener.onRefresh(this);
        }
    }

    protected void updateMoreLoadListener() {
        isMoreLoading = true;
        if (footView != null) {
            footView.onRefreshing(this);
        }
        if (refreshListener != null) {
            refreshListener.onRefreshLoadMore(this);
        }
    }

    public void setMoreLoad(boolean isMoreLoad) {
        this.isMoreLoad = isMoreLoad;
    }

    public void setIsOverLay(boolean isOverLay) {
        this.isOverlay = isOverLay;
    }

    public void createAnimatorTranslationY(final View v, final float h, final FrameLayout fl) {
        ViewPropertyAnimatorCompat viewPropertyAnimatorCompat = ViewCompat.animate(v);
        viewPropertyAnimatorCompat.setDuration(200);
        viewPropertyAnimatorCompat.setInterpolator(new DecelerateInterpolator());
        viewPropertyAnimatorCompat.translationY(h);
        viewPropertyAnimatorCompat.start();
        viewPropertyAnimatorCompat.setUpdateListener(new ViewPropertyAnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(View view) {
                float height = v.getTranslationY();
                fl.getLayoutParams().height = (int) Math.abs(height);
                fl.requestLayout();
            }
        });
    }

    /**
     * 当前内容是否可以向上滚动
     */
    public boolean canChildScrollUp() {
        if (mChildView == null) {
            return false;
        }
        return mChildView.canScrollVertically(-1);
    }

    /**
     * 当前内容是否可以向下滚动
     */
    public boolean canChildScrollDown() {
        if (mChildView == null) {
            return false;
        }
        return mChildView.canScrollVertically(1);
    }

    private void setWaveHigher() {
        headHeight = HIGHER_HEAD_HEIGHT;
        waveHeight = HIGHER_WAVE_HEIGHT;
        footHeight = HIGHER_FOOT_HEIGHT;
        RefreshWaveView.DefaultViewHeight = HIGHER_HEAD_HEIGHT;
        RefreshWaveView.DefaultWaveHeight = HIGHER_WAVE_HEIGHT;
    }

    private void setWaveDefault() {
        headHeight = DEFAULT_HEAD_HEIGHT;
        waveHeight = DEFAULT_WAVE_HEIGHT;
        footHeight = DEFAULT_FOOT_HEIGHT;
        RefreshWaveView.DefaultViewHeight = DEFAULT_HEAD_HEIGHT;
        RefreshWaveView.DefaultWaveHeight = DEFAULT_WAVE_HEIGHT;
    }

    /**
     * 停止刷新
     */
    public void finishRefreshing() {
        if (isRefreshing) {
            isRefreshing = false;
            if (mChildView != null) {
                ViewPropertyAnimatorCompat viewPropertyAnimatorCompat = ViewCompat.animate(mChildView);
                viewPropertyAnimatorCompat.setDuration(200);
                viewPropertyAnimatorCompat.y(mChildView.getTranslationY());
                viewPropertyAnimatorCompat.translationY(0);
                viewPropertyAnimatorCompat.setInterpolator(new DecelerateInterpolator());
                viewPropertyAnimatorCompat.start();
            }
            if (headView != null) headView.onComplete(this);
            if (refreshListener != null) refreshListener.onRefreshFinish();
            setHeadProgressValue(0);
        }
    }

    public void finishRefresh() {
        this.post(this::finishRefreshing);
    }

    public void finishMoreLoad() {
        this.post(this::finishMoreLoading);
    }

    public void finishMoreLoading() {
        if (isMoreLoading) {
            isMoreLoading = false;
            if (mChildView != null) {
                ViewPropertyAnimatorCompat viewPropertyAnimatorCompat = ViewCompat.animate(mChildView);
                viewPropertyAnimatorCompat.setDuration(200);
                viewPropertyAnimatorCompat.y(mChildView.getTranslationY());
                viewPropertyAnimatorCompat.translationY(0);
                viewPropertyAnimatorCompat.setInterpolator(new DecelerateInterpolator());
                viewPropertyAnimatorCompat.start();
            }
            if (footView != null) footView.onComplete(this);
            if (refreshListener != null) refreshListener.onLoadMoreFinish();
            setFootProgressValue(0);
        }
    }

    /**
     * 设置头部进度
     *
     * @param progressValue 当前进度
     */
    public void setHeadProgressValue(int progressValue) {
        if (headView != null) headView.setProgressValue(progressValue);
    }

    /**
     * 设置底部进度
     *
     * @param progressValue 当前进度
     */
    public void setFootProgressValue(int progressValue) {
        if (footView != null) footView.setProgressValue(progressValue);
    }

    public void setHeaderView(final View headerView) {
        if (headerView.getParent() == null) {
            mHeadLayout.addView(headerView);
        }
    }

    public void setFooterView(final View footerView) {
        if (footerView.getParent() == null) {
            mFootLayout.addView(footerView);
        }
    }

    public void setWaveHeight(float waveHeight) {
        this.mWaveHeight = waveHeight;
    }

    public void setHeaderHeight(float headHeight) {
        this.mHeadHeight = headHeight;
    }

    public void setFootHeight(float mFootHeight) {
        this.mFootHeight = mFootHeight;
    }

    public void setMaterialRefreshListener(RefreshListener refreshListener) {
        this.refreshListener = refreshListener;
    }
}